// ---------------------------------------------------------------------
//
// -- 游戏界面
// -- author £
//
// ---------------------------------------------------------------------

const CommonInfo = require('CommonInfo'),
    HexagonUtil = require('HexagonUtil'),
    CommonUtil = require('CommonUtil'),
    SoundManager = require('SoundManager');

const GRID_OFFSET = 310,
    AREA_OFFSET = -680,
    TIP_OFFSET = -300,

// const GRID_OFFSET = 480,
//     AREA_OFFSET = -640,
//     TIP_OFFSET = -300,

    RADIUS = 40,
    ERASE_DELAY = 0.05,

    LASER_TIME = 1.0,
    HAMMER_TIME = 1.2,
    BOMB_TIME = 1,
    BREAK_DELAY = 0.1,
    DELAY_ERASE = 0.3,
    SKILL_ICON_OFFSET = 120;

cc.Class({
    extends: cc.Component,

    properties: {
        gridLayer: cc.Node,
        itemLayer: cc.Node,
        opLayer: cc.Node,
        gridP: cc.Prefab,
        scoreView: require('ScoreView'),
        skillBtnLayer: cc.Node,
        btnRefresh: cc.Button,
        // numLeftTime: require('BaseNum'),
        lbLeftRefresh: cc.Label,
        revivePanel: require('RevivePanel'),
        coinRevivePanel: require('CoinRevivePanel'),
        playLayer: cc.Node,
        sharedView: cc.Sprite,
        btnReturn: cc.Node,
        floatScoreLayer: cc.Node,
        floatScore: cc.Prefab,
        endTip: cc.Node,
        gameInstruction: require('GameInstruction'),
        skillMask: require('GameMask'),
        skillLayer: require('SkillLayer'),
        btnSkillLaser: cc.Button,
        btnSkillHammer: cc.Button,
        btnSkillBomb: cc.Button,
        skillHammerArea: cc.Node,
        skillBombArea: cc.Node,
        hammerBadge: require('Badge'),
        laserBadge: require('Badge'),
        bombBadge: require('Badge'),
        refreshBadge: require('Badge'),
        iconAddHammer: cc.Node,
        iconAddLaser: cc.Node,
        iconAddBomb: cc.Node,
        iconAddRefresh: cc.Node,
        techPanel: require('TechPanel'),
        getItemPanel: require('GetItemPanel'),
        surpassView: require('SurpassView'),
        videoAlert: require('AlertWindow'),
        deadMask: require('GameMask'),
        returnPanel: require('ReturnPanel'),

        itemAreas: {
            default: [],
            type: cc.Node,
        },
        opAreas: {
            default: [],
            type: cc.Node,
        },
        items: {
            default: [],
            type: require('HexagonItem'),
        },
        ops: {
            default: [],
            type: require('HexagonItem'),
        },
    },

    ctor: function () {
        this._update = false;
        this._useSub = true;
        this._totalDt = 0;
        this._updateCount = 0;
        this.tex = new cc.Texture2D();
        this._uItr = 0;
        this._gridStartY = 0;
        this._grids = [];
        this._stratLocation = null;
        this._deltaLocation = { x: 0, y: 0 };
        this._enables = [true, true, true];
        this._inMove = false;
        this._skillGridIndex = -1;
        this._hammerEnable = false;
        this._bombEnable = false;
        this._canGetLaser = false;
        this._canGetBomb = false;
        this._canGetHammer = false;
        this._canGetRefresh = false;
    },

    onLoad() {
        let UIManager = require('UIManager'),
            row, col, i,
            startCol = 5, startX, startY,
            grid;

        this._mediator = require('GameConfig').gameMediator;
        this.sharedView.node.y = - UIManager.getRootY();
        this.sharedView.node.height = UIManager.getRealH();
        this._gridStartY = GRID_OFFSET - UIManager.getRootY();
        this.skillBtnLayer.y -= UIManager.getDeltaH();
        // this.skillBtnLayer.y = - UIManager.getRealH() * 0.77;
        this.skillHammerArea.y = this.skillBtnLayer.y
        this.skillBombArea.y = this.skillBtnLayer.y
        startX = HexagonUtil.getLocation(3).x * 2;
        startY = this._gridStartY;
        this.endTip.y = this._gridStartY + TIP_OFFSET;
        this.videoAlert.node.y = - UIManager.getRealH() * 0.5;
        // this.btnRefresh.enableAutoGrayEffect = true;
        this.gameInstruction.resize(this._gridStartY + AREA_OFFSET);

        for (i = 0; i < 3; ++i) {
            this.itemAreas[i].y = this.opAreas[i].y =
                this._gridStartY + AREA_OFFSET;
        }

        for (row = 0; row < 9; ++row) {
            if (row >= 1 && row <= 4) {
                startX += HexagonUtil.getLocation(2).x;
                startY += HexagonUtil.getLocation(2).y;
                ++startCol;
            } else if (row >= 5 && row <= 8) {
                startX += HexagonUtil.getLocation(1).x;
                startY += HexagonUtil.getLocation(1).y;
                --startCol;
            }

            for (col = 0; col < startCol; ++col) {
                grid = cc.instantiate(this.gridP);
                this.gridLayer.addChild(grid);
                grid.x = startX + HexagonUtil.getLocation(0).x * col;
                grid.y = startY;
                this._grids[this._grids.length] = grid.getComponent(require('HexagonGrid'));
            }
        }

        for (i = 0; i < 3; ++i) {
            this.opAreas[i].on('touchstart', this.selectItemHandler, this);
        }

        // for (i = 0; i < 3; ++i) {
        //     this._scorePool.put(cc.instantiate(this.floatScore));
        // }

        let m = this._mediator;

        this.getItemPanel.btnGet.on('click', m.getItemHandler, m);
        this.getItemPanel.btnSkip.on('click', this.hideGetItem, this);
        this.getItemPanel.btnGetOld.on('click', this.hideGetItem, this);
        this.revivePanel.btnSkip.on('click', m.skipReviveHandler, m);
        this.revivePanel.btnRevive.on('click', m.reviveHandler, m);
        this.revivePanel.btnReviveOld.on('click', m.reviveOldHandler, m);
        this.coinRevivePanel.btnSkip.on('click', m.skipReviveHandler, m);
        this.coinRevivePanel.btnUse.on('click', m.useCoinReviveHandler, m);
        this.btnReturn.on('click', m.showReturnHandler, m);
        this.btnRefresh.node.on('click', m.refreshHandler, m);
        this.btnSkillLaser.node.on('click', m.laserHandler, m);
        this.skillHammerArea.on('touchstart', this.selectHammerHandler, this);
        this.skillBombArea.on('touchstart', this.selectBombHandler, this);
        this.btnSkillHammer.node.on('click', m.clickHammerHandler, m);
        this.btnSkillBomb.node.on('click', m.clickBombHandler, m);
        this.techPanel.setData(null, null, m.techHideHandler, m);
        this.returnPanel.setData(null, null, m.returnHandler, m);
    },

    start() {
        this._mediator.register(this);

    },

    onShow: function () {
        this.deadMask.hide();
        this.scoreView.show();
        this.scoreView.updateScore(0);
        this.surpassView.setHead(CommonInfo.userInfo);
        this.showPlayerLayer();
        this.endTip.active = false;
        this.btnReturn.active = true;
    },

    onHide: function () {
        this.hideRevive();
        this.revivePanel.clear();
        this.gameInstruction.stop();
        this.surpassView.reset();
        this.stop();
        // CommonUtil.resetPool(this._scorePool, this.floatScoreLayer);
        this.floatScoreLayer.removeAllChildren();
        this.skillLayer.node.stopAllActions();
        this.skillLayer.reset();
        this.skillMask.hide();
        this.techPanel.hide();
        this.hideVideoAlert();
        this._inMove = false;
    },

    roundReset: function () {
        let i, len = this._grids.length;

        this._enables = [true, true, true];

        for (i = 0; i < len; ++i) {
            this._grids[i].reset();
        }

        for (i = 0; i < 3; ++i) {
            this.itemAreas[i].opacity = 255;
            this.items[i].node.x =
                this.items[i].node.y = 0;
            this.ops[i].node.x =
                this.ops[i].node.y = 0;
            this.ops[i].node.active = false;
        }

        // CommonUtil.resetPool(this._scorePool, this.floatScoreLayer);
        // this.skillHammerArea.active = true;
        // this.skillBombArea.active = true;
        this.floatScoreLayer.removeAllChildren();
        this.skillLayer.node.stopAllActions();
        this.skillLayer.reset();
        this.skillMask.hide();
        this.revivePanel.hide();
        this.coinRevivePanel.hide();
        this.getItemPanel.hide();
        this.hideVideoAlert();
        this.deadMask.hide();
    },

    showReturnPanel: function (cur, best) {
        this.returnPanel.show(cur, best);
    },

    showTechPanel: function () {
        this.techPanel.show();
    },

    showHL: function (indexes) {
        let i, len = this._grids.length;

        for (i = 0; i < len; ++i) {
            this._grids[i].setHL(indexes && indexes.indexOf(i) >= 0);
        }
    },

    showGrids: function (indexes, color) {
        let i, len = indexes.length;

        for (i = 0; i < len; ++i) {
            this._grids[indexes[i]].setGrid(color);
        }

        SoundManager.playSE('place');
    },

    createNewItem: function (index, data) {
        this.items[index].setData(data);
        this.ops[index].setData(data);
    },

    setItemEnable: function (enables) {
        let i;

        this._enables = enables;

        for (i = 0; i < 3; ++i) {
            this.itemAreas[i].opacity = this._enables[i] ? 255 : 30;
        }
    },

    getItemEnable: function (index) {
        return this._enables[index];
    },

    eraseGrids: function (indexes) {
        let i, j,
            len = indexes.length, len2,
            count = 0;

        for (i = 0; i < len; ++i) {
            len2 = indexes[i].length;

            for (j = 0; j < len2; ++j) {
                this._grids[indexes[i][j]].erase((count++) * ERASE_DELAY);
            }
        }

        SoundManager.playSE('erase');
    },

    updateScore: function (score) {
        this.scoreView.updateScore(score);
    },

    updateRefreshTime: function (count, count2, total) {
        this._canGetRefresh = count2 > 0;
        this.btnRefresh.interactable = count2 > 0 || count > 0;
        // this.iconAddRefresh.active = count2 > 0 && count <= 0;
        

        if (total) {
            this.lbLeftRefresh.string = '剩余次数: ' + count + '/' + total;
        } else {
            this.refreshBadge.updateNum(count);
        }
    },

    updateSurpassScore: function (start, end, percent) {
        this.surpassView.updateScore(start, end, percent);
    },

    showRevive: function (coinRevive) {
        if (coinRevive)
            this.coinRevivePanel.show();
        else
            this.revivePanel.show();

        this.endTip.stopAllActions();
        this.endTip.opacity = 0;
        this.endTip.active = false;
        this._update = false;
    },

    hideRevive: function () {
        this.revivePanel.hide();
        this.coinRevivePanel.hide();
        this.endTip.active = false;
        // this.playLayer.active = true;
    },

    autoRevive: function () {
        this.endTip.active = false;
    },

    getReviveData: function () {
        return this.revivePanel.getData();
    },

    showGetItem: function (itemName, count) {
        this.getItemPanel.show(itemName, count);
    },

    showPlayerLayer: function () {
        require('Platform').scaleSharedCanvas();
        this.playLayer.active = true;
        this._update = true;
    },

    stop: function () {
        this._update = false;
        this.sharedView.spriteFrame = null;
    },

    startDrawSub: function () {
        this._update = true;
    },

    showFloatScore: function (d, index) {
        // if (!this._scorePool.size()) return;

        // let score = this._scorePool.get(),
        let score = cc.instantiate(this.floatScore),
            scoreC = score.getComponent(require('FloatScore'));

        // scoreC.pool = this._scorePool;
        score.x = this._grids[index].node.x;
        score.y = this._grids[index].node.y;
        this.floatScoreLayer.addChild(score);
        scoreC.show(d);
    },

    refreshItems: function (items) {
        let i;

        for (i = 0; i < 3; ++i) {
            this.items[i].setData(items[i]);
            this.ops[i].setData(items[i]);
        }
    },

    showEndTip: function () {
        this.deadMask.show();
        this.endTip.active = true;
        this.endTip.opacity = 0;
        require('ActionLib').FADE_SCALE_SHOW(
            this.endTip, 0.3,
            0, 0, 1, 1
        );
    },

    playInstruction: function () {
        this.gameInstruction.play();
    },

    recover: function (data) {
        let i, len = data.grids.length;

        this.roundReset();
        this.gameInstruction.stop();
        this.scoreView.updateScore(data.score);

        // if (data.laserCount !== null && data.laserCount !== undefined)
        //     this.laserEnable(data.laserCount, data.getRefreshCount);

        // if (data.hammerCount !== null && data.hammerCount !== undefined)
        //     this.hammerEnable(data.hammerCount);

        // if (data.bombCount !== null && data.bombCount !== undefined)
        //     this.bombEnable(data.bombCount);

        for (i = 0; i < len; ++i) {
            if (!data.grids[i].free) {
                this._grids[i].setGrid(data.grids[i].colorIndex);
            }
        }
    },

    revive: function () {
        this.roundReset();
        this._update = true;
    },

    useLaser: function (uidata, erases) {
        let i, len = uidata.length, data,
            laserData = [], laser,
            startNode, endNode;

        for (i = 0; i < len; ++i) {
            data = uidata[i];
            laser = {};
            endNode = this._grids[data.end].node;
            startNode = this._grids[data.start].node;
            laser.x = startNode.x + (endNode.x - startNode.x) * 0.5;
            laser.y = startNode.y + (endNode.y - startNode.y) * 0.5;
            laser.d = data.d;
            laserData[i] = laser;
        }

        SoundManager.playSE('laser');
        this.skillLayer.showLaserSkill(laserData);
        this.delaySkillErase(erases);
        this.delayOp(LASER_TIME);
    },

    useBomb: function (index, erases) {
        this.skillLayer.showBombSkill(
            this._grids[index].node.x,
            this._grids[index].node.y,
        );
        SoundManager.playSE('bomb');
        this.delaySkillErase(erases);
        this.delayOp(BOMB_TIME);
    },

    useHammer: function (index, colorIndex) {
        this.skillLayer.showHammerSkill(
            this._grids[index].node.x,
            this._grids[index].node.y,
            colorIndex
        );
        SoundManager.playSE('hammer');
        CommonUtil.delay(
            this.skillLayer.node,
            BREAK_DELAY,
            function () {
                this._grids[index].reset();
            }, this
        );
        this.delayOp(HAMMER_TIME);
    },

    delaySkillErase: function (erases) {
        // CommonUtil.delay(
        //     this.skillLayer.node,
        //     DELAY_ERASE,
        //     function () {
        //         let len = erases.length;

        //         for (let i = 0; i < len; ++i) {
        //             this._grids[erases[i]].erase((count ++) * ERASE_DELAY);
        //         }
        //     }, this
        // );
        let len = erases.length;

        this.gameInstruction.stop();

        for (let i = 0; i < len; ++i) {
            this._grids[erases[i]].erase(DELAY_ERASE);
        }
    },

    delayOp: function (time) {
        this.skillMask.show(1, true);
        CommonUtil.delay(
            this.skillLayer.node,
            time,
            function () {
                this.skillMask.hide();
                this.skillLayer.reset();
            }, this
        );
    },

    laserEnable: function (count, count2) {
        this._canGetLaser = count2 > 0;
        this.btnSkillLaser.interactable = count2 > 0 || count > 0;
        // this.iconAddLaser.active = count2 > 0 && count <= 0;
        this.laserBadge.updateNum(count);
    },

    hammerEnable: function (count, count2) {
        this._canGetHammer = count2 > 0;
        this._hammerEnable = count > 0;
        // this.skillHammerArea.active = count > 0;
        this.btnSkillHammer.interactable = count2 > 0 || count > 0;
        this.hammerBadge.updateNum(count);
    },

    bombEnable: function (count, count2) {
        this._canGetBomb = count2 > 0;
        this._bombEnable = count > 0;
        // this.skillBombArea.active = count > 0;
        this.btnSkillBomb.interactable = count2 > 0 || count > 0;
        this.bombBadge.updateNum(count);
    },

    showVideoAlert: function (content, closeFunc, closeScope) {
        this.videoAlert.setData(
            content, null, 
            closeFunc, closeScope
        );
        this.videoAlert.show();
    },

    hideVideoAlert: function () {
        this.videoAlert.hide(true);
    },

    _getSelectGridIndex: function (x, y) {
        let i, len = this._grids.length, dis,
            checkIndex = -1;

        for (i = 0; i < len; ++i) {
            dis = cc.pDistance(this._grids[i].node,
                {
                    x: x,
                    y: y
                });

            if (dis <= RADIUS) {
                checkIndex = i;
                break;
            }
        }

        return checkIndex;
    },

    hideGetItem: function () {
        this.getItemPanel.hide();
        this.hideVideoAlert();
    },

    //-------------------------------------------------------------------

    StartGameS: function (data) {
        this.refreshItems(data.items);
        this.laserEnable(true);
        this.hammerEnable(true);
        this.bombEnable(true);
    },

    //-------------------------------------------------------------------

    selectBombHandler: function (event) {
        if (!this._bombEnable) return;
        if (this._inMove) return;

        this._inMove = true;
        this._skillGridIndex = -1;
        this.skillLayer.showBomb(SKILL_ICON_OFFSET);
        this._stratLocation = event.getLocation();

        this.skillBombArea.off('touchmove', this.moveBombHandler, this);
        this.skillBombArea.off('touchend', this.moveBombEndHandler, this);
        this.skillBombArea.off('touchcancel', this.moveBombEndHandler, this);

        this.skillBombArea.on('touchmove', this.moveBombHandler, this);
        this.skillBombArea.on('touchend', this.moveBombEndHandler, this);
        this.skillBombArea.on('touchcancel', this.moveBombEndHandler, this);
    },

    moveBombHandler: function (event) {
        let curLocation = event.getLocation(),
            checkIndex;

        this.skillLayer.updateBombPos(
            curLocation.x - this._stratLocation.x,
            curLocation.y - this._stratLocation.y + SKILL_ICON_OFFSET
        );
        this._skillGridIndex = this._getSelectGridIndex(
            curLocation.x - this._stratLocation.x + this.skillBombArea.x,
            curLocation.y - this._stratLocation.y + SKILL_ICON_OFFSET + this.skillBombArea.y
        );

        if (this._skillGridIndex === -1) {
            this.skillLayer.updateBombRegion(null);
        } else {
            this.skillLayer.updateBombRegion(
                this._grids[this._skillGridIndex].node.x,
                this._grids[this._skillGridIndex].node.y
            );
        }
    },

    moveBombEndHandler: function (event) {
        this._inMove = false;
        this.skillLayer.hideBomb();

        if (this._skillGridIndex >= 0) {
            this._mediator.bombHandler(this._skillGridIndex);
        }

        this.skillBombArea.off('touchmove', this.moveBombHandler, this);
        this.skillBombArea.off('touchend', this.moveBombEndHandler, this);
        this.skillBombArea.off('touchcancel', this.moveBombEndHandler, this);
    },

    selectHammerHandler: function (event) {
        if (!this._hammerEnable) return;
        if (this._inMove) return;

        this._inMove = true;
        this._skillGridIndex = -1;
        this.skillLayer.showHammer(SKILL_ICON_OFFSET);
        this._stratLocation = event.getLocation();

        this.skillHammerArea.off('touchmove', this.moveHammerHandler, this);
        this.skillHammerArea.off('touchend', this.moveHammerEndHandler, this);
        this.skillHammerArea.off('touchcancel', this.moveHammerEndHandler, this);

        this.skillHammerArea.on('touchmove', this.moveHammerHandler, this);
        this.skillHammerArea.on('touchend', this.moveHammerEndHandler, this);
        this.skillHammerArea.on('touchcancel', this.moveHammerEndHandler, this);
    },

    moveHammerHandler: function (event) {
        let curLocation = event.getLocation(),
            checkIndex;

        this.skillLayer.updateHammerPos(
            curLocation.x - this._stratLocation.x,
            curLocation.y - this._stratLocation.y + SKILL_ICON_OFFSET
        );
        this._skillGridIndex = this._getSelectGridIndex(
            curLocation.x - this._stratLocation.x + this.skillHammerArea.x,
            curLocation.y - this._stratLocation.y + SKILL_ICON_OFFSET + this.skillHammerArea.y
        );

        if (this._skillGridIndex === -1) {
            this.skillLayer.updateHammerRegion(null);
        } else {
            this.skillLayer.updateHammerRegion(
                this._grids[this._skillGridIndex].node.x,
                this._grids[this._skillGridIndex].node.y
            );
        }
    },

    moveHammerEndHandler: function (event) {
        this._inMove = false;
        this.skillLayer.hideHammer();

        if (this._skillGridIndex >= 0) {
            this._mediator.hammerHandler(this._skillGridIndex);
        }

        this.skillHammerArea.off('touchmove', this.moveHammerHandler, this);
        this.skillHammerArea.off('touchend', this.moveHammerEndHandler, this);
        this.skillHammerArea.off('touchcancel', this.moveHammerEndHandler, this);
    },

    selectItemHandler: function (event) {
        if (this._inMove) return;

        let index = this.opAreas.indexOf(event.target);

        if (!this.getItemEnable(index)) return;

        this.gameInstruction.stop();
        this._inMove = true;
        this.items[index].node.active = false;
        this.ops[index].node.active = true;
        this.ops[index].node.x = 0;
        this.ops[index].node.y = 0;
        this._stratLocation = event.getLocation();
        this._mediator.selectItemHandler(index);

        for (i = 0; i < 3; ++i) {
            this.opAreas[i].off('touchmove', this.moveItemHandler, this);
            this.opAreas[i].off('touchend', this.moveEndHandler, this);
            this.opAreas[i].off('touchcancel', this.moveEndHandler, this);
        }

        this.opAreas[index].on('touchmove', this.moveItemHandler, this);
        this.opAreas[index].on('touchend', this.moveEndHandler, this);
        this.opAreas[index].on('touchcancel', this.moveEndHandler, this);
    },

    moveItemHandler: function (event) {
        let index = this.opAreas.indexOf(event.target),
            curLocation = event.getLocation(),
            firstLocation = this.ops[index].getFisrtLocation(),
            gIndex, i, len = this._grids.length, dis,
            checkIndex = -1;

        this._deltaLocation.x = curLocation.x - this._stratLocation.x;
        this._deltaLocation.y = curLocation.y - this._stratLocation.y;
        this.ops[index].node.x = this._deltaLocation.x;
        this.ops[index].node.y = this._deltaLocation.y;

        checkIndex = this._getSelectGridIndex(
            this._deltaLocation.x + this.opAreas[index].x + firstLocation.x,
            this._deltaLocation.y + this.opAreas[index].y + firstLocation.y
        );
        this._mediator.moveHandler(checkIndex);
    },

    moveEndHandler: function (event) {
        let index = this.opAreas.indexOf(event.target);

        this.items[index].node.active = true;
        this.ops[index].node.active = false;
        // this.showHL(null);

        this.opAreas[index].off('touchmove', this.moveItemHandler, this);
        this.opAreas[index].off('touchend', this.moveEndHandler, this);
        this.opAreas[index].off('touchcancel', this.moveEndHandler, this);
        this._inMove = false;
        this._mediator.moveEndHandler();
    },

    update(dt) {
        if (!this._useSub) return;
        if (!this._update) return;

        ++this._updateCount;
        this._totalDt += dt;

        if (this._updateCount === 60) {
            let avgDt = this._totalDt / this._updateCount;

            this._useSub = avgDt <= 0.036;
            this.sharedView.spriteFrame = null;
            console.log('avgDt:', avgDt);
            console.log('this._useSub', this._useSub);
        }

        if (this._uItr !== 2) {
            ++this._uItr;
        }

        this._uItr = 0;
        require('Platform').updateSub(this.tex, this.sharedView);
    },
});
